#include "stdafx.h"
#include "base/system/thread_utils.h"
#include "base/system/module_walker.h"
#include "base/system/win_internal.h"

CString GetThreadNameById(DWORD nPid, DWORD nTid)
{
    ScopedHandle hThread(::OpenThread(THREAD_QUERY_INFORMATION, FALSE, nTid));
    if(NULL == hThread) {
        return _T("");
    }

    ScopedModule hNtDll(::LoadLibrary(_T("ntdll.dll")));
    if(NULL == hNtDll) {
        return _T("");
    }

    FuncNtQueryInformationThread pFunc = (FuncNtQueryInformationThread)::GetProcAddress(hNtDll, "NtQueryInformationThread");
    if(NULL == pFunc) {
        return _T("");
    }

    ULONG nRetLen = 0;
    PVOID pThreadStartAddr = NULL;
    pFunc(hThread, ThreadQuerySetWin32StartAddress, &pThreadStartAddr, sizeof(pThreadStartAddr), &nRetLen);
    if(NULL == pThreadStartAddr) {
        return _T("");
    }

    ModuleWalker oWalker;
    if(!oWalker.Start(nPid)) {
        return _T("");
    }

    MODULEENTRY32 *pModuleEntry = oWalker.Get();
    do {
        if(pModuleEntry->modBaseAddr <= pThreadStartAddr
            && pModuleEntry->modBaseAddr + pModuleEntry->modBaseSize >= pThreadStartAddr)
        {
            return CString(pModuleEntry->szModule);
        }
    } while(oWalker.Next());

    return _T("");
}